<?php
namespace app\index\controller;
use app\model\Msg as MsgModel;
use think\Db;

use app\lib\baidu\Api as baiduApi;
use app\lib\baidu\Api360 as api360;
use app\lib\baidu\Tongyi as TongyiApi;
use app\lib\baidu\Moonshot as Moonshot;

require_once '../extend/baidu.bos/BaiduBce.phar';
use BaiduBce\BceClientConfigOptions;
use BaiduBce\Util\MimeTypes;
use BaiduBce\Http\HttpHeaders;
use BaiduBce\Services\Bos\BosClient;


class Msg extends Base
{
    public function __construct(){
        $model = new MsgModel();
        $this->model = $model;
        parent::__construct();
    }

    public function index($session_sn){
        $ulogin = $this->login_user;
        $model = $this->model;
        // $map_params = [
        //     ['key'=>'session_sn','type'=>'='],
        // ];
        // $map = getSearchParam($map_params);
        $map = [
            ['session_sn','=',$session_sn],
            ['user_id','=',$ulogin['id']]
        ];

        $list = $model->where($map)->order('id','asc')->select();
        $msg = [];
        foreach ($list as $k => $vo) {
            $ctime = date('Y-m-d',$vo['ctime']);
            // $vo['ctime'] = date('h:i a',$vo['ctime']);
            // $vo['rtime'] = date('h:i a',$vo['ctime']);
            $vo['ctime'] = date('H:i:s',$vo['ctime']);
            $vo['rtime'] = date('H:i:s',$vo['rtime']);
            if ($vo['type'] == 'text') {
                $vo['message'] = myTextareaShow($vo['message']);
                $vo['reply'] = myTextareaShow($vo['reply']);
            }elseif($vo['type'] == 'htsc'){
                $vo['message'] = json_decode($vo['message'],true);
            }elseif ($vo['type'] == 'aidraw') {
                $vo['message'] = json_decode($vo['message'],true);
                $vo['reply'] = json_decode($vo['reply'],true);
            }
            
            $msg[$ctime][] = $vo;
        }

        
        $session = Db::name('session')->where('session_sn',$session_sn)->find();
        $session['ctime'] = date('H:i:s',$session['ctime']);
        // $assistant_id = Db::name('session')->where('session_sn',$session_sn)->value('assistant_id');
        $assistant_id = $session['assistant_id'];
        $assistant = Db::name('assistant')->where('id',$assistant_id)->find();

        $wait_msgs = Db::name('htsc')->where([
            ['user_id','=',$ulogin['id']],
            ['status','=',0]
        ])->column('msg_id');
        
        return json(['code'=>2000,'list'=>$msg,'assistant'=>$assistant,'wait_msgs'=>$wait_msgs,'session'=>$session]);
    }

    public function getRpley($id){
        $data = Db::name('msg')->where('id',$id)->find();
        if (empty($data) || empty($data['reply'])) {
            return json(['code'=>5000]);
        }
        if ($data['type'] == 'aidraw') {
            $data['reply'] = json_decode($data['reply'],true);
        }
        return json(['code'=>2000,'data'=>[
            'reply'=>$data['reply'],
            'rtime'=>date('H:i:s',$data['rtime']),
            'type'=>$data['type']
        ]]);
    }

    // 获取指令优化
    public function getPrompt($task_id){
        $data = Db::name('prompt')->where('task_id',$task_id)->find();

        if (empty($data)) {
            return json(['code'=>5000]);
        }
        if ($data['status'] == 0) {
            $api = new baiduApi();
            $result = $api->singleOptimizeInfo($data['task_id']);
            if ($result['status'] == 1) {
                if ($result['data']['processStatus'] == 2) {
                    Db::name('prompt')->where('task_id',$data['task_id'])->update([
                        'status'=>1,
                        'content'=>json_encode($result['data'],JSON_UNESCAPED_UNICODE)
                    ]);

                    return json(['code'=>2000,'data'=>[
                        'content'=>$result['data']['content'],
                        'optimizeContent'=>$result['data']['optimizeContent'],
                    ]]);
                }elseif ($result['data']['processStatus'] == 3){
                    Db::name('prompt')->where('task_id',$data['task_id'])->update([
                        'status'=>-1,
                        'content'=>json_encode($result['data'],JSON_UNESCAPED_UNICODE)
                    ]);
                    return json(['code'=>5001]);
                }
            }

            return json(['code'=>5000]);
        }
        $content = json_decode($data['content'],true);
        return json(['code'=>2000,'data'=>[
            'content'=>$content['content'],
            'optimizeContent'=>$content['optimizeContent'],
        ]]);
    }

    
    // public function save(){
    //     $ulogin = $this->login_user;
    //     $fields = [
    //         'must'=>['session_sn','message'],
    //         'nomust'=>['reply']
    //     ];
    //     $save_data = paramFilter(request()->param(),$fields);
    //     if (!empty($save_data['error_msg'])) {
    //         return json(['code'=>5000,'msg'=>$save_data['error_msg']]);
    //     }

    //     $save_data['user_id'] = $ulogin['id'];
    //     $assistant_id = Db::name('session')->where('session_sn',$save_data['session_sn'])->value('assistant_id');
    //     $save_data['assistant_id'] = $assistant_id;
    //     $save_data['ctime'] = time();
    //     $save_data['rtime'] = time() + 1;
    //     $save_data['duration'] = 1;
    //     $msg_id = Db::name('msg')->insertGetId($save_data);
        
    //     $result = [
    //         'code'=>2000,
    //         'id'=>$msg_id
    //     ];
    //     return json($result);
    // } 

    // 获取历史记录
    public function getMessages($session_sn,$model){
        $user_id = $this->login_user['id'];
        $map = [
            ['session_sn','=',$session_sn],
            ['user_id','=',$user_id]
        ];
        $msgs = MsgModel::field('message,reply')->where($map)->order('id','desc')->limit(3)->select();
        $messages = [];

        for($i = count($msgs) - 1;$i >= 0;$i--){
            if (empty($msgs[$i]['message']) || empty($msgs[$i]['reply'])) {
                continue;
            }

            if ( in_array($model,['farui']) ) {
                $messages[] = [
                    'user'=>$msgs[$i]['message'],
                    'bot'=>$msgs[$i]['reply']
                ];
            }else{
                $messages[] = [
                    'role'=>'user',
                    'content'=>$msgs[$i]['message']
                ];
                $messages[] = [
                    'role'=>'assistant',
                    'content'=>$msgs[$i]['reply']
                ];
            }
            
        }
        
        return $messages;
    }

  

    // public function getToken($message,$session_sn){
    //     $ulogin = $this->login_user;
    //     $message = trim($message);
    //     if (empty($message)) {
    //         return json(['code'=>5000]);
    //     }
    //     $check_msg = preg_replace("/[^\x{4e00}-\x{9fa5}a-zA-Z0-9]/u", '', $message);
    //     $check_msg = strtolower($check_msg);
    //     if (empty($check_msg)) {
    //         return json(['code'=>5000]);
    //     }

    //     $assistant_id = Db::name('session')->where('session_sn',$session_sn)->value('assistant_id');
    //     $assistant = Db::name('assistant')->where('id',$assistant_id)->find();

    //     $api_url = $assistant['api_url'];
    //     $api_param = json_decode($assistant['api_param'],true);

    //     $uuid = uuidCreate();
    //     if ($assistant['type'] == 'baidu') {
    //         $api = new baiduApi();
    //         $token = $api->token($api_param);
    //         if (empty($token['access_token'])) {
    //             return json(['code'=>5000,'msg'=>'token获取失败']);
    //         }
    //         $messages = $this->getMessages($session_sn,$assistant['type']);
    //         $messages[] = [
    //             'role'=>'user',
    //             'content'=>$message
    //         ];
    //         return json(['code'=>2000,'data'=>[
    //             'api_url'=>$api_url,
    //             'access_token'=>$token['access_token'],
    //             'messages'=>$messages,
    //             'uuid'=>$uuid
    //         ]]);
    //     }elseif($assistant['type'] == 'tongyi'){
    //         $params = [
    //             'uuid'=>$uuid,
    //             'message'=>$message,
    //             'session_sn'=>$session_sn
    //         ];

    //         return json(['code'=>2000,'data'=>[
    //             'api_url'=>$api_url,
    //             'params'=>$params,
    //             'uuid'=>$uuid
    //         ]]);
    //     }
    // }

    

    public function singleOptimize($message=''){
        if ( empty(trim($message)) ) {
            return json(['code'=>5000,'msg'=>'请输入需要优化的指令']);
        }
        $ulogin = $this->login_user;
        $api = new baiduApi();
        // $message = '增程式混动车型和插电式混合车型购买建议';
        $result = $api->singleOptimize($message);
        if ($result['status'] == 1) {
            $task_id = $result['data']['id'];
            Db::name('prompt')->insert([
                'user_id'=>$ulogin['id'],
                'task_id'=>$task_id,
            ]);
            return json(['code'=>2000,'msg'=>'success','data'=>$task_id]);
        }else{
            return json(['code'=>5000,'msg'=>$result['msg']]);
        }
    }

    public function chatapi(){
        set_time_limit ( 0 );
        ini_set('memory_limit','-1');
        ini_set('max_execution_time',0);

        $ulogin = $this->login_user;
        $fields = [
            'must'=>['session_sn','message'],
        ];
        $params = paramFilter(request()->param(),$fields);
        if (!empty($params['error_msg'])) {
            return apiResult(5000,$params['error_msg']);
        }

        $curtime = time();
        $message = trim($params['message']);
        if (empty($message)) {
            return apiResult('5000','message不能为空');
        }

        // 获取配置
        $assistant_id = Db::name('session')->where('session_sn',$params['session_sn'])->value('assistant_id');
        $assistant = Db::name('assistant')->where('id',$assistant_id)->find();
        $config = json_decode($assistant['api_param'],true);
        if ( empty($config) ) {
            return apiResult('5000','model不存在');
        }
        $config['api_url'] = $assistant['api_url'];
        $params['system'] = $assistant['system'];
        $params['model'] = $assistant['type'];
        $config['model'] = $params['model'];

        // 获取历史消息
        $messages = $this->getMessages($params['session_sn'],$params['model']);

        if (in_array($params['model'], ['ERNIE-4.0'])) {
            $api = new baiduApi();
            $token = $api->token($config);
            if (empty($token['access_token'])) {
                return apiResult('5000','模型调用失败');
            }
            $messages[] = [
                'role'=>'user',
                'content'=>$message
            ];
            $result = $api->chat($config['api_url'],$token['access_token'],$messages,$params['system']);
        }elseif(in_array($params['model'], ['qwen-turbo','qwen-plus','qwen-max','qwen-max-0403','qwen-max-0107','qwen-max-1201','qwen-max-longcontext','farui-plus'])){
            $api = new TongyiApi();
            $config['model'] = $params['model'];
            $messages[] = [
                'role'=>'user',
                'content'=>$message
            ];
            $result = $api->chat($config['api_url'],$config,$messages);
        }elseif(in_array($params['model'], ['farui'])){
            $api = new TongyiApi();
            $body = [
                'prompt'=>$message
            ];
            if (!empty($messages)) {
                $body['history'] = $messages;
            }
            $result = $api->farui($config['api_url'],$body,$config);
        }elseif(in_array($params['model'], ['moonshot-v1-8k','moonshot-v1-32k','moonshot-v1-128k'])){
            $api = new Moonshot();
            $messages[] = [
                'role'=>'user',
                'content'=>$message
            ];
            $result = $api->chat($config['api_url'],$config,$messages);
        }

        if($result['status'] == 0){
            return apiResult('5000',$result['msg']);
        }

        $save_data = [
            'user_id'=>$ulogin['id'],
            'assistant_id'=>$assistant_id,
            'session_sn'=>$params['session_sn'],
            'message'=>$message,
            'reply'=>$result['answer'],
            'model'=>$params['model'],
            'ctime'=>$curtime,
            'rtime'=>time(),
        ];
        $save_data['duration'] = $save_data['rtime'] - $save_data['ctime'];
        $msg_id = MsgModel::insertGetId($save_data);
        if ( $msg_id > 0 ) {
            // 计费接口

        }
        return apiResult('2000','获取成功',[
            'id'=>$msg_id,
            'reply'=>myTextareaShow($save_data['reply'])
        ]);
    }


    // public function faruiSse($session_sn,$message,$uuid){
    //     $assistant_id = Db::name('session')->where('session_sn',$session_sn)->value('assistant_id');
    //     $assistant = Db::name('assistant')->where('id',$assistant_id)->find();

    //     $api_url = $assistant['api_url'];
    //     $api_param = json_decode($assistant['api_param'],true);
    //     $api_param['uuid'] = $uuid;

    //     $api = new TongyiApi();
    //     $history = $this->getMessages($session_sn,$message,'tongyi');
    //     $messages = [
    //         'prompt'=>$message
    //     ];
    //     if (!empty($history)) {
    //         $messages['history'] = $history;
    //     }
    //     $result = $api->faruiSse($api_url,$messages,$api_param);
    //     if ($result['status'] == 1) {
    //         // 如果已结束，则保存记录
    //         if ($result['is_finish'] == 1) {
    //             $ulogin = $this->login_user;
    //             $save_data = [
    //                 'user_id'=>$ulogin['id'],
    //                 'session_sn'=>$session_sn,
    //                 'assistant_id'=>$assistant_id,
    //                 'message'=>$message,
    //                 'reply'=>$result['answer'],
    //                 'ctime'=>time(),
    //                 'rtime'=>time()+1,
    //                 'duration'=>1,
    //             ];
    //             Db::name('msg')->insert($save_data);
    //         }

    //         return json(['code'=>2000,'data'=>[
    //             'reply'=>$result['answer'],
    //             'is_finish'=>$result['is_finish']
    //         ]]);
    //     }else{
    //         return json(['code'=>2000,'data'=>[
    //             'reply'=>$result['answer'],
    //             'is_finish'=>1
    //         ]]);
    //     }
    // }

    public function htsc(){
        $ulogin = $this->login_user;
        $fields = [
            'must'=>['type','session_sn'],
        ];
        $params = paramFilter(request()->param(),$fields);
        if (!empty($params['error_msg'])) {
            return json(['code'=>5000,'msg'=>$params['error_msg']]);
        }

        // //调用配置文件中的参数
        $bos_config = config('config.baidu_bos');
        // //新建BosClient
        $client = new BosClient($bos_config);
        $bucketName = 'falvai';
        
        $file = $this->request->file('file');
        $ext = explode(".", $file->getInfo()['name']);//拆分获取图片名
        $ext = strtolower($ext[count($ext) - 1]);//取图片的后缀名
        $types = ["pdf", "doc", 'docx'];
        if (!in_array($ext, $types)) {
            return json(['code'=>5000,'msg'=>'仅支持支持PDF/doc/docx格式文件']);
        }
        // 将文件上传到本地
        $info = $file->move('uploads');
        $objectName = uuidCreate().'.'.$ext;
        $name_path =str_replace('\\',"/",$info->getSaveName());//文件存储的路径
        $result = $client->putObjectFromFile($bucketName, $objectName,'uploads/'.$name_path);

        $url = "uploads/".$info->getSaveName();//文件本地目录
        unset($info);//如果不释放这个变量下面的unlink()函数会报错。
        if (file_exists($url)) {
             unlink($url);//删除本地文件
        }
        $file_url = 'https://falvai.bj.bcebos.com/'.$objectName;

        $assistant_id = Db::name('session')->where('session_sn',$params['session_sn'])->value('assistant_id');
        $assistant = Db::name('assistant')->where('id',$assistant_id)->find();

        $message = [
            'name'=>$file->getInfo()['name'],
            'ext'=>$ext,
            'type'=>$params['type'],
            'url'=>$objectName
        ];
        $save_data = [
            'user_id'=>$ulogin['id'],
            'session_sn'=>$params['session_sn'],
            'assistant_id'=>$assistant_id,
            'message'=>json_encode($message,JSON_UNESCAPED_UNICODE),
            'ctime'=>time(),
            'type'=>'htsc'
        ];

        $result = (new baiduApi())->htsc($file_url,$params['type']);
        if ($result['status'] == 1) {
            $msg_id = Db::name('msg')->insertGetId($save_data);
            Db::name('htsc')->insert([
                'msg_id'=>$msg_id,
                'user_id'=>$save_data['user_id'],
                'task_id'=>$result['task_id']
            ]);
            return json(['code'=>2000,'data'=>[
                'message'=>$message,
                'ctime'=>date('Y-m-d H:i:s',$save_data['ctime']),
                'reply'=>'文档已上传成功，正在加急分析中，请稍后',
                'rtime'=>date('Y-m-d H:i:s'),
            ],'msg_id'=>$msg_id]);
        }else{
            $save_data['reply'] = $result['msg'];
            $save_data['rtime'] = time();
            $save_data['duration'] = time() - $save_data['ctime'];
            Db::name('msg')->insert($save_data);
            return json(['code'=>2001,'data'=>[
                'message'=>$message,
                'ctime'=>date('Y-m-d H:i:s',$save_data['ctime']),
                'reply'=>$save_data['reply'],
                'rtime'=>date('Y-m-d H:i:s',$save_data['rtime']),
            ]]);
        }
    }

    public function aiDraw(){
        $ulogin = $this->login_user;
        $fields = [
            'must'=>['prompt','chicun','session_sn'],
            'nomust'=>['num']
        ];
        $params = paramFilter(request()->param(),$fields);
        if (!empty($params['error_msg'])) {
            return json(['code'=>5000,'msg'=>$params['error_msg']]);
        }
        if (empty($params['num'])) {
            $params['num'] = 1;
        }
        if ($params['num'] > 8 || $params['num'] < 1) {
            return json(['code'=>5000,'msg'=>'图片数量请设置在1-8张']);
        }
        $chicun = explode('x',$params['chicun']);

        

        // //调用配置文件中的参数
        // $bos_config = config('config.baidu_bos');
        // // //新建BosClient
        // $client = new BosClient($bos_config);
        // $bucketName = 'falvai';
        
        // $file = $this->request->file('file');
        // $ext = explode(".", $file->getInfo()['name']);//拆分获取图片名
        // $ext = strtolower($ext[count($ext) - 1]);//取图片的后缀名
        // $types = ["pdf", "doc", 'docx'];
        // if (!in_array($ext, $types)) {
        //     return json(['code'=>5000,'msg'=>'仅支持支持PDF/doc/docx格式文件']);
        // }
        // // 将文件上传到本地
        // $info = $file->move('uploads');
        // $objectName = uuidCreate().'.'.$ext;
        // $name_path =str_replace('\\',"/",$info->getSaveName());//文件存储的路径
        // $result = $client->putObjectFromFile($bucketName, $objectName,'uploads/'.$name_path);

        // $url = "uploads/".$info->getSaveName();//文件本地目录
        // unset($info);//如果不释放这个变量下面的unlink()函数会报错。
        // if (file_exists($url)) {
        //      unlink($url);//删除本地文件
        // }
        // $file_url = 'https://falvai.bj.bcebos.com/'.$objectName;

        $assistant_id = Db::name('session')->where('session_sn',$params['session_sn'])->value('assistant_id');
        $assistant = Db::name('assistant')->where('id',$assistant_id)->find();

        $message = [
            // 'name'=>$file->getInfo()['name'],
            // 'ext'=>$ext,
            // 'type'=>$params['type'],
            // 'url'=>$objectName
            'prompt'=>$params['prompt'],
            'chicun'=>$params['chicun'],
            'num'=>$params['num']
        ];
        $save_data = [
            'user_id'=>$ulogin['id'],
            'session_sn'=>$params['session_sn'],
            'assistant_id'=>$assistant_id,
            'message'=>json_encode($message,JSON_UNESCAPED_UNICODE),
            'ctime'=>time(),
            'type'=>'aidraw'
        ];

        $api = new baiduApi();
        $token = $api->token([
            'client_id'=>'nuCDgwPHzU3JSCZ9BaahYT44',
            'client_secret'=>'LlyWXJJJD3ew7vFC27kxBWwJspR6nSn3'
        ]);
        if (empty($token['access_token'])) {
            return json(['code'=>5000,'msg'=>'token获取失败']);
        }
        $result = $api->txt2imgv2($token['access_token'],[
            'prompt'=>$params['prompt'],
            'width'=>intval($chicun[0]),
            'height'=>intval($chicun[1]),
            'image_num'=>intval($params['num'])
        ]);
        if ($result['status'] == 1) {
            $msg_id = Db::name('msg')->insertGetId($save_data);
            Db::name('aidraw')->insert([
                'msg_id'=>$msg_id,
                'user_id'=>$save_data['user_id'],
                'task_id'=>$result['task_id']
            ]);
            return json(['code'=>2000,'data'=>[
                'message'=>$message,
                'ctime'=>date('H:i:s',$save_data['ctime']),
                'reply'=>'请求发送成功，正在加急生成中，请稍后',
                'rtime'=>date('H:i:s'),
            ],'msg_id'=>$msg_id]);
        }else{
            $save_data['reply'] = $result['msg'];
            $save_data['rtime'] = time();
            $save_data['duration'] = time() - $save_data['ctime'];
            Db::name('msg')->insert($save_data);
            return json(['code'=>2001,'data'=>[
                'message'=>$message,
                'ctime'=>date('H:i:s',$save_data['ctime']),
                'reply'=>$save_data['reply'],
                'rtime'=>date('H:i:s',$save_data['rtime']),
            ]]);
        }
    }

    // 全局sse返回内容
    public $sse_reply = '';

    // 输出sse答复内容
    public function sendSseReply(){
        $content = json_encode(['is_end'=>false,'ctime'=>time(),'result'=>$this->sse_reply],JSON_UNESCAPED_UNICODE);
        echo "data:".$content."\n\n";
        //刷新缓冲区
        ob_flush();
        //将输出缓冲区的内容立即发送到客户端
        flush();
    }

    public function chatsse(){
        // 这行代码用于关闭输出缓冲。关闭后，脚本的输出将立即发送到浏览器，而不是等待缓冲区填满或脚本执行完毕。
        ini_set('output_buffering', 'off');
        // 这行代码禁用了 zlib 压缩。通常情况下，启用 zlib 压缩可以减小发送到浏览器的数据量，但对于服务器发送事件来说，实时性更重要，因此需要禁用压缩。
        ini_set('zlib.output_compression', false);
        // 这行代码使用循环来清空所有当前激活的输出缓冲区。ob_end_flush() 函数会刷新并关闭最内层的输出缓冲区，@ 符号用于抑制可能出现的错误或警告。
        while (@ob_end_flush()) {}
        // 这行代码设置 HTTP 响应的 Content-Type 为 text/event-stream，这是服务器发送事件（SSE）的 MIME 类型。
        header('Content-Type: text/event-stream');
        // 这行代码设置 HTTP 响应的 Cache-Control 为 no-cache，告诉浏览器不要缓存此响应。
        header('Cache-Control: no-cache');
        // 这行代码设置 HTTP 响应的 Connection 为 keep-alive，保持长连接，以便服务器可以持续发送事件到客户端。
        header('Connection: keep-alive');
        // 这行代码设置 HTTP 响应的自定义头部 X-Accel-Buffering 为 no，用于禁用某些代理或 Web 服务器（如 Nginx）的缓冲。这有助于确保服务器发送事件在传输过程中不会受到缓冲影响
        header('X-Accel-Buffering: no');


        $param = file_get_contents('php://input');
        $param = json_decode($param,true);
        $fields = [
            'must'=>['session_sn','message'],
        ];
        // $params = [
        //     'session_sn'=>'2A898395093240FEBD82329D59EAC815',
        //     'message'=>'你好'
        // ];
        $params = paramFilter($param,$fields);
        if (!empty($params['error_msg'])) {
            return apiResult(5000,$params['error_msg']);
        }
        // $fields = [
        //     'must'=>['session_sn','message'],
        // ];
        // $params = paramFilter(request()->param(),$fields);
        // if (!empty($params['error_msg'])) {
        //     return apiResult(5000,$params['error_msg']);
        // }

        $curtime = time();
        $message = trim($params['message']);
        if (empty($message)) {
            return apiResult('5000','message不能为空');
        }
        
        // 获取配置
        $assistant_id = Db::name('session')->where('session_sn',$params['session_sn'])->value('assistant_id');
        $assistant = Db::name('assistant')->where('id',$assistant_id)->find();
        $config = json_decode($assistant['api_param'],true);
        if ( empty($config) ) {
            return apiResult('5000','model不存在');
        }
        $config['api_url'] = $assistant['api_url'];
        $params['system'] = $assistant['system'];
        $params['model'] = $assistant['type'];
        $config['model'] = $params['model'];

        // 获取历史消息
        $messages = $this->getMessages($params['session_sn'],$params['model']);

        if (in_array($params['model'], ['ERNIE-4.0'])) {
            $api = new baiduApi();
            $token = $api->token($config);
            if (empty($token['access_token'])) {
                return apiResult('5000','模型调用失败');
            }
            $messages[] = [
                'role'=>'user',
                'content'=>$message
            ];

            $api_url = $config['api_url'].'?access_token='.$token['access_token'];
            $body = [
                "messages" => $messages
            ];
            if (!empty($params['system'])) {
                $body['system'] = $params['system'];
            }
            $this->callBaiduWorkshopSSE($api_url, $body, function ($msg) {
                if ($msg["type"] == "DATA") {
                    $this->sse_reply .= $msg["content"]['result'];
                    $this->sendSseReply();
                }
            });
        }elseif(in_array($params['model'], ['qwen-turbo','qwen-plus','qwen-max','qwen-max-0403','qwen-max-0107','qwen-max-1201','qwen-max-longcontext','farui-plus'])){
            $messages[] = [
                'role'=>'user',
                'content'=>$message
            ];
            $body = [
                'model'=>$params['model'],
                'input'=>[
                    'messages'=>$messages
                ]
            ];
           
            $this->callTongyiWorkshopSSE($config['api_url'],$config, $body, function ($msg) {
                if ($msg["type"] == "DATA") {
                    $this->sse_reply = $msg["content"]['output']['text'];
                    $content = json_encode(['is_end'=>false,'ctime'=>time(),'result'=>$this->sse_reply],JSON_UNESCAPED_UNICODE);
                    $this->sendSseReply();
                }
            });
        }elseif(in_array($params['model'], ['farui'])){
            $api = new TongyiApi();
            $body = [
                'prompt'=>$message
            ];
            if (!empty($messages)) {
                $body['history'] = $messages;
            }
            $config['uuid'] = uuidCreate();
            
            do {
                $result = $api->faruiSse($config['api_url'],$body,$config);
                if ($result['status'] == 1) {
                    $this->sse_reply = $result['answer'];
                    if ($result['is_finish'] == 0) {
                        $content = json_encode(['is_end'=>false,'ctime'=>time(),'result'=>$this->sse_reply],JSON_UNESCAPED_UNICODE);
                        $this->sendSseReply();

                        sleep(1);
                    }
                }
            } while ($result['status']==1 && $result['is_finish'] == 0);
        }elseif(in_array($params['model'], ['moonshot-v1-8k','moonshot-v1-32k','moonshot-v1-128k'])){
            $messages[] = [
                'role'=>'user',
                'content'=>$message
            ];
            $body = [
                'model'=>$params['model'],
                'messages'=>$messages,
                'stream'=>true
            ];
           
            $this->callMoonshotWorkshopSSE($config['api_url'],$config, $body, function ($msg) {
                if ($msg["type"] == "DATA") {
                    $see_content = $msg["content"]['choices'][0]['delta']['content'];
                    if (!empty($see_content)) {
                        $this->sse_reply .= $see_content;
                        $content = json_encode(['is_end'=>false,'ctime'=>time(),'result'=>$this->sse_reply],JSON_UNESCAPED_UNICODE);
                        $this->sendSseReply();
                    }
                } else if ($msg["type"] == "END") {
                    $content = json_encode(['is_end'=>true,'ctime'=>time(),'result'=>$this->sse_reply],JSON_UNESCAPED_UNICODE);
                    echo "data:".$content."\n\n";
                } else {
                    // var_dump($msg);
                }
            });
        }

        if (!empty($this->sse_reply)) {
            $ulogin = $this->login_user;
            $save_data = [
                'user_id'=>$ulogin['id'],
                'assistant_id'=>$assistant_id,
                'session_sn'=>$params['session_sn'],
                'message'=>$message,
                'reply'=>$this->sse_reply,
                'model'=>$params['model'],
                'ctime'=>$curtime,
                'rtime'=>time()
            ];
            $save_data['duration'] = $save_data['rtime'] - $save_data['ctime'];
            $msg_id = MsgModel::insertGetId($save_data);
            if ( $msg_id > 0 ) {
                // 计费接口

            }

            $content = json_encode(['is_end'=>true,'ctime'=>time(),'result'=>$this->sse_reply,'id'=>$msg_id],JSON_UNESCAPED_UNICODE);
            echo "data:".$content."\n\n";
        }

        
    }

    public function callMoonshotWorkshopSSE($url,$api_param, $body, $onMessage) {
        return (new class() {
            private $buffer = "";
            private $dataMsgBuffer = "";

            public function call($url,$api_param, $body, $onMessage)
            {
                // $body['stream'] = true;
                $curl = curl_init();
                curl_setopt_array($curl, array(
                    CURLOPT_URL => $url,
                    CURLOPT_RETURNTRANSFER => true,
                    CURLOPT_ENCODING => '',
                    CURLOPT_MAXREDIRS => 10,
                    CURLOPT_TIMEOUT => 0,
                    CURLOPT_FOLLOWLOCATION => true,
                    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
                    CURLOPT_CUSTOMREQUEST => 'POST',
                    CURLOPT_POSTFIELDS => json_encode($body),
                    CURLOPT_HTTPHEADER => array(
                        'Content-Type: application/json',
                        'Authorization:Bearer '.$api_param['key']

                    ),
                    CURLOPT_WRITEFUNCTION => function ($curl, $str) use ($onMessage) {
                        $this->buffer = $this->buffer . $str;
                        $lines = explode("\n", $this->buffer);
                        $this->buffer = array_pop($lines);
                        foreach ($lines as $line) {
                            if ($line == "") { //读取到空行，一个数据块发送完成
                                $onMessage([
                                    "type" => "DATA",
                                    "content" => json_decode($this->dataMsgBuffer,true)
                                ]);
                                $this->dataMsgBuffer = "";
                                continue;
                            }
                            $msgPart = explode(":", $line, 2);
                            $type = $msgPart[0];
                            $content = $msgPart[1];
                            if ($type == 'data') { //数据块没有收到空行之前放入buffer中
                                $this->dataMsgBuffer = $this->dataMsgBuffer . trim($content);
                            } else if ($type == '' && $content != '') { //服务端发送的注释，用于保证链接不断开
                                $onMessage([
                                    "type" => "COMMENT",
                                    "content" => trim($content)
                                ]);
                            } else {
                                $onMessage([
                                    "type" => $type,
                                    "content" => trim($content)
                                ]);
                            }
                        }
                        return strlen($str);
                    }
                ));
                curl_exec($curl);
                if (curl_errno($curl)) {
                    $onMessage([
                        "type" => "ERROR",
                        "content" => curl_strerror(curl_errno($curl))
                    ]);
                } else {
                    $onMessage([
                        "type" => "END"
                    ]);
                }
                curl_close($curl);
            }
        })->call($url,$api_param, $body, $onMessage);
    }

    public function callTongyiWorkshopSSE($url,$api_param, $body, $onMessage) {
        return (new class() {
            private $buffer = "";
            private $dataMsgBuffer = "";

            public function call($url,$api_param, $body, $onMessage)
            {
                // $body['stream'] = true;
                $curl = curl_init();
                curl_setopt_array($curl, array(
                    CURLOPT_URL => $url,
                    CURLOPT_RETURNTRANSFER => true,
                    CURLOPT_ENCODING => '',
                    CURLOPT_MAXREDIRS => 10,
                    CURLOPT_TIMEOUT => 0,
                    CURLOPT_FOLLOWLOCATION => true,
                    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
                    CURLOPT_CUSTOMREQUEST => 'POST',
                    CURLOPT_POSTFIELDS => json_encode($body),
                    CURLOPT_HTTPHEADER => array(
                        'Content-Type: application/json',
                        'Authorization:Bearer '.$api_param['api_key'],
                        'Accept:text/event-stream'

                    ),
                    CURLOPT_WRITEFUNCTION => function ($curl, $str) use ($onMessage) {
                        $this->buffer = $this->buffer . $str;
                        $lines = explode("\n", $this->buffer);
                        $this->buffer = array_pop($lines);
                        foreach ($lines as $line) {
                            if ($line == "") { //读取到空行，一个数据块发送完成
                                $onMessage([
                                    "type" => "DATA",
                                    "content" => json_decode($this->dataMsgBuffer,true)
                                ]);
                                $this->dataMsgBuffer = "";
                                continue;
                            }
                            $msgPart = explode(":", $line, 2);
                            $type = $msgPart[0];
                            $content = $msgPart[1];
                            if ($type == 'data') { //数据块没有收到空行之前放入buffer中
                                $this->dataMsgBuffer = $this->dataMsgBuffer . trim($content);
                            } else if ($type == '' && $content != '') { //服务端发送的注释，用于保证链接不断开
                                $onMessage([
                                    "type" => "COMMENT",
                                    "content" => trim($content)
                                ]);
                            } else {
                                $onMessage([
                                    "type" => $type,
                                    "content" => trim($content)
                                ]);
                            }
                        }
                        return strlen($str);
                    }
                ));
                curl_exec($curl);
                if (curl_errno($curl)) {
                    $onMessage([
                        "type" => "ERROR",
                        "content" => curl_strerror(curl_errno($curl))
                    ]);
                } else {
                    $onMessage([
                        "type" => "END"
                    ]);
                }
                curl_close($curl);
            }
        })->call($url,$api_param, $body, $onMessage);
    }

    public function callBaiduWorkshopSSE($url, $body, $onMessage) {
        return (new class() {
            private $buffer = "";
            private $dataMsgBuffer = "";

            public function call($url, $body, $onMessage)
            {
                $body['stream'] = true;
                $curl = curl_init();
                curl_setopt_array($curl, array(
                    CURLOPT_URL => $url,
                    CURLOPT_RETURNTRANSFER => true,
                    CURLOPT_ENCODING => '',
                    CURLOPT_MAXREDIRS => 10,
                    CURLOPT_TIMEOUT => 0,
                    CURLOPT_FOLLOWLOCATION => true,
                    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
                    CURLOPT_CUSTOMREQUEST => 'POST',
                    CURLOPT_POSTFIELDS => json_encode($body),
                    CURLOPT_HTTPHEADER => array(
                        'Content-Type: application/json'
                    ),
                    CURLOPT_WRITEFUNCTION => function ($curl, $str) use ($onMessage) {
                        $this->buffer = $this->buffer . $str;
                        $lines = explode("\n", $this->buffer);
                        $this->buffer = array_pop($lines);
                        foreach ($lines as $line) {
                            if ($line == "") { //读取到空行，一个数据块发送完成
                                $onMessage([
                                    "type" => "DATA",
                                    "content" => json_decode($this->dataMsgBuffer,true)
                                ]);
                                $this->dataMsgBuffer = "";
                                continue;
                            }
                            $msgPart = explode(":", $line, 2);
                            $type = $msgPart[0];
                            $content = $msgPart[1];
                            if ($type == 'data') { //数据块没有收到空行之前放入buffer中
                                $this->dataMsgBuffer = $this->dataMsgBuffer . trim($content);
                            } else if ($type == '' && $content != '') { //服务端发送的注释，用于保证链接不断开
                                $onMessage([
                                    "type" => "COMMENT",
                                    "content" => trim($content)
                                ]);
                            } else {
                                $onMessage([
                                    "type" => $type,
                                    "content" => trim($content)
                                ]);
                            }
                        }
                        return strlen($str);
                    }
                ));
                curl_exec($curl);
                if (curl_errno($curl)) {
                    $onMessage([
                        "type" => "ERROR",
                        "content" => curl_strerror(curl_errno($curl))
                    ]);
                } else {
                    $onMessage([
                        "type" => "END"
                    ]);
                }
                curl_close($curl);
            }
        })->call($url, $body, $onMessage);
    }


   
}
